#if MF_FRAMEWORK_VERSION_V4_3 || MF_FRAMEWORK_VERSION_V4_2
using Microsoft.SPOT;
#endif

using System;
using System.Collections;
using System.Threading;

namespace Timers
{
    public class TimersManager
    {
        private Hashtable _timers = new Hashtable();

        public event TimerManagerCallbackHandler TimerElapsed;

        public void CreateTimer(string Name, int FirstTickMs, int PeriodMs)
        {
            var timerdata = new TimerData() { Name = Name, FirstTickMs = FirstTickMs, PeriodMs = PeriodMs, Enabled = false };
            var timer = new Timer(timersCallback, timerdata, Timeout.Infinite, Timeout.Infinite);
            timerdata.TimerObject = timer;

            _timers[Name] = timerdata;
        }

        public void CreateTimer(string Name, int FirstTickMs)
        {
            CreateTimer(Name, FirstTickMs, Timeout.Infinite);
        }

        public void DestroyTimer(string Name)
        {
            var timerdata = _timers[Name] as TimerData;

            if (timerdata == null) return;

            timerdata.TimerObject.Dispose();
            _timers.Remove(Name);
        }

        public void StartTimer(string Name)
        {
            var timerdata = _timers[Name] as TimerData;

            if (timerdata == null) return;

            timerdata.TimerObject.Change(timerdata.FirstTickMs, timerdata.PeriodMs);

            timerdata.Enabled = true;
        }

        public void StopTimer(string Name)
        {
            if (_timers[Name] == null) return;

            var timerdata = _timers[Name] as TimerData;

            timerdata.TimerObject.Change(Timeout.Infinite, Timeout.Infinite);

            timerdata.Enabled = false;
        }

        private void timersCallback(object state)
        {
            var timerdata = state as TimerData;

            if (TimerElapsed != null && timerdata.Enabled && _timers[timerdata.Name] != null)
            {
                TimerElapsed(typeof(TimersManager), new TimerManagerEventArgs(timerdata));
            }
        }
    }

    public delegate void TimerManagerCallbackHandler(object sender, TimerManagerEventArgs e);

    public class TimerData
    {
        public bool Enabled { get; set; }

        public int FirstTickMs { get; set; }

        public string Name { get; set; }

        public int PeriodMs { get; set; }

        public Timer TimerObject { get; set; }
    }

    public class TimerManagerEventArgs : EventArgs
    {
        private TimerData _timerdata;

        public TimerManagerEventArgs(TimerData timerdata)
            : base()
        {
            _timerdata = timerdata;
        }

        public TimerData TimerData
        {
            get { return _timerdata; }
        }
    }
}